<?php

namespace App\Http\Controllers\Api;

use App\Constant;
use App\Enums\DivideStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentStatus;
use App\Enums\ProductStatus;
use App\Events\OrderPaid;
use App\Models\AgentConfig;
use App\Models\Enterprise;
use App\Models\Order;
use App\Models\OrderPayment;
use App\Services\AdaPayService;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use Throwable;

class AdaPayController
{
    public $adaPayService;

    /**
     * 支付成功回调.
     *
     * @throws Throwable
     */
    public function notify()
    {
        $postData = json_decode(request()->data, 1);
        $postDataStr = json_encode($postData, JSON_UNESCAPED_UNICODE);
        $postSignStr = request()->sign ?? '';
        $appId = request()->app_id ?? '';
        if (empty($appId)) {
            $appId = request()->appId ?? '';
        }

        \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->info('NOTIFY', request()->all());
        \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->info('NOTIFY', $postData);

        /** @var AgentConfig $config */
        $config = AgentConfig::query()
            ->where('config_key', AgentConfig::ADAPAY_APP_ID)
            ->where('config_value', $appId)->first();
        if ($config) {
            $config = AgentConfig::query()
                ->where('agent_id', $config->agent_id)
                ->pluck('config_value', 'config_key');
            $this->adaPayService = new AdaPayService($config);
            $signFlag = $this->adaPayService->verifySign($postDataStr, $postSignStr);
        } else {
            \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->error('NOTIFY', ['APP ID 未配置']);

            return 'SUCCESS';
        }

        if ($signFlag) {
            switch (request()->type) {
                case 'payment.succeeded':
                    $this->paymentSucceeded($postData);

                    break;

                case 'payment.failed':
                    $this->paymentFailed($postData);

                    break;

                case 'corp_member.succeeded':
                    $this->corpMemberSucceeded($postData);

                    break;

                case 'corp_member.failed':
                    $this->corpMemberFailed($postData);

                    break;

                case 'refund.succeeded':
                    $this->refundSucceeded($postData);

                    break;

                case 'refund.failed':
                    $this->refundFailed($postData);

                    break;
            }
        } else {
            \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->error('NOTIFY', ['验证签名失败']);
        }
    }

    /**
     * 支付成功回调.
     *
     * @throws Throwable
     */
    private function paymentSucceeded(array $data): string
    {
        /** @var OrderPayment $payment */
        $payment = OrderPayment::query()->where('out_order_no', $data['order_no'])->first();
        if ($payment && $payment->pay_status->is(PaymentStatus::PAYING)) {
            \DB::transaction(function () use ($payment, $data) {
                /** @var Order $order */
                $order = Order::query()->find($payment->order_id);

                if ($order->order_status->is(OrderStatus::CANCEL)) {
                    $payment->pay_status = PaymentStatus::REFUNDED;
                    $payment->divide_status = DivideStatus::FAILED;
                    $payment->save();
                    $this->adaPayService->refund($data['id'], 'REFUND_' . $payment->out_order_no, $data['pay_amt']);
                } else {
                    $payment->pay_status = PaymentStatus::FINISHED;
                    $payment->divide_status = DivideStatus::DIVIDED;
                    $payment->pay_time = Carbon::parse($data['created_time']);
                    $payment->receive_amount = toFen($data['pay_amt'] - $data['fee_amt']);
                    if ($payment->agent_receive_amount - toFen($data['fee_amt']) > 0) {
                        $payment->agent_receive_amount = $payment->agent_receive_amount - toFen($data['fee_amt']);
                    }
                    $payment->save();

                    $order = $payment->order;
                    if ($order->order_status->is(OrderStatus::NOT_PAY())) {
                        $order->order_status = OrderStatus::PAID;
                        $order->save();

                        //转售订单标记为停止发行
                        $product = $order->product;
                        if ($order->is_resale) {
                            $product->status = ProductStatus::STOP;
                            $product->save();
                        }

                        OrderPaid::dispatch($order);
                    }
                }
            });
        }

        return 'SUCCESS';
    }

    /**
     * 支付失败回调.
     */
    private function paymentFailed(array $data)
    {
    }

    /**
     * 开户成功回调.
     */
    private function corpMemberSucceeded(array $data)
    {
        /** @var Enterprise $enterprise */
        $enterprise = Enterprise::query()->where('code', $data['member_id'])->first();
        if ($enterprise) {
            $enterprise->applicationStatus = 'COMPLETED';
            $enterprise->save();
        }
    }

    /**
     * 开户失败回调.
     */
    private function corpMemberFailed(array $data)
    {
        /** @var Enterprise $enterprise */
        $enterprise = Enterprise::query()->where('code', $data['member_id'])->first();
        if ($enterprise) {
            $enterprise->applicationStatus = 'REVIEW_BACK';
            $enterprise->auditOpinion = Arr::get($data, 'audit_desc');
            $enterprise->save();
        }
    }

    /**
     * 退款成功回调.
     */
    private function refundSucceeded(array $data)
    {
    }

    /**
     * 退款失败回调.
     */
    private function refundFailed(array $data)
    {
    }
}
